const express= require ('express')
const multer= require ('multer')
const cors= require ('cors')
const path = require("path");
const fse = require("fs-extra");
const fs = require("fs");
const formidable = require('formidable');
const multiparty = require('multiparty');
const bodyParser = require('body-parser');

const app = express()
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))//配置body-parser
// app.use((req, res, next) => {
//   res.setHeader("Access-Control-Allow-Origin", "*");
//   res.setHeader(
//     "Access-Control-Allow-Methods",
//     "OPTIONS, GET, POST, PUT, PATCH, DELETE" // what matters here is that OPTIONS is present
//   );
//   res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization", "Access-Control-Allow-Origin");
//   next();
// });
// const upload = multer({ dest: 'uploads/' })

// 大文件存储目录
const UPLOAD_DIR = path.resolve(__dirname, "upload");

// 提取文件后缀名
const extractExt = (filename) =>
  filename.slice(filename.lastIndexOf("."), filename.length);

/**
 * 针对 path 创建 readStream 并写入 writeStream,写入完成之后删除文件
 * @param {String} path
 * @param {String} writeStream
 */
const pipeStream = (path, writeStream) =>
  new Promise((resolve) => {
    const readStream = fse.createReadStream(path);
    readStream.on("end", () => {
      fse.unlinkSync(path);
      resolve();
    });
    readStream.pipe(writeStream);
  });

/**
 * 读取所有的 chunk 合并到 filePath 中
 * @param {String} filePath 文件存储路径
 * @param {String} chunkDir chunk存储文件夹名称
 * @param {String} size 每一个chunk的大小
 */
async function mergeFileChunk(filePath, chunkDir, size) {
  // 获取chunk列表
  const chunkPaths = await fse.readdir(chunkDir);
  // 根据切片下标进行排序  否则直接读取目录的获得的顺序可能会错乱
  chunkPaths.sort((a, b) => a.split("-")[1] - b.split("-")[1]);
  await Promise.all(
    chunkPaths.map((chunkPath, index) =>
      pipeStream(
        path.resolve(chunkDir, chunkPath),
        // 指定位置创建可写流
        fse.createWriteStream(filePath, {
          start: index * size,
          end: (index + 1) * size,
        })
      )
    )
  );
  fse.rmdirSync(chunkDir); // 合并后删除保存切片的目录
}
const upload = multer({
  storage: multer.diskStorage({
      destination: function (req, file, cb) {
          cb(null, './uploads/')
      },
      filename: function (req, file, cb) {
          // fieldname是表单的name值，也就是我们设定的“logo”，
          // originalname是文件上传时的名字，可以根据它获取后缀，
          // encoding，mimetype 我就不详细介绍了，可以自行输出查看。
          const { fieldname, originalname, encoding, mimetype } = file
          console.log(fieldname, originalname);
          const after = originalname.split('.')[1] ? '.' + originalname.split('.')[1] : '.jpg'
          cb(null, originalname);
      }
  })
})

app.post('/chunk', async (req, res) => {
  const multipart = new multiparty.Form();
  multipart.parse(req, async (err, fields, files) => {
    if (err) return;
    const chunkHash = fields.chunkHash[0];
    const fileHash = fields.fileHash[0];
    const chunk = files.chunk[0];
    const chunkDir = path.resolve(UPLOAD_DIR, `${fileHash}-chunks`);
    // // 切片目录不存在，创建切片目录
    if (!fse.existsSync(chunkDir)) {
      await fse.mkdirs(chunkDir);
    } else {
      // let fileList = fs.readdirSync(chunkDir);   //返回文件和子目录的数组
      // fileList.forEach(function(file,index){
      //   fs.unlinkSync(path.join(chunkDir,file));
      // });
    }
    await fse.move(chunk.path, `${chunkDir}/${chunkHash}`);
    res.send({ code: 200, data: "", msg: "上传成功" })
  })
})
app.post('/merge', async (req, res) => {
    const { fileName, fileSize, size, hash } = req.body;
  // console.log('data ====>', ctx.request.body);
  const ext = extractExt(fileName);
  console.log(fileName,11);
  console.log(ext,11);
  // const filePath = path.resolve(UPLOAD_DIR, `${hash}${ext}`);
  const filePath = path.resolve(UPLOAD_DIR, `${fileName}`);
  const chunkDir = path.resolve(UPLOAD_DIR, `${hash}-chunks`);
  await mergeFileChunk(filePath, chunkDir, size);
  res.send({ code: 200, data: req.body, msg: "合并成功" });
})
app.post('/aa', async (req, res) => {
  console.log(req.body);
  res.send({ code: 200, data: req.body, msg: "11111" });
})
var server = app.listen(3000, function () {
  var host = server.address().address
  var port = server.address().port
  console.log("应用实例，访问地址为 http://%s:%s", host, port)
})
